import {EventEmitter} from "events";
import {logger} from "../utils/logger";
import {Channel, Connection, Message} from 'amqplib'
import {generate} from 'shortid'
import {USER_CENTER_EXCHANGE} from "./constant";

export class Engine extends EventEmitter {
  private channel: Channel;
  private consumerTag: string;
  readonly id: string = generate()

  constructor(readonly appId: string, readonly userId: string) {
    super()
  }

  async connect(connection: Connection) {

    this.channel = await connection.createChannel()
    this.channel.on('error', error => {
      logger.error('connectToBackend channel error ' + error)

      this.emit("error", error)
    })

    await this.channel.assertExchange(USER_CENTER_EXCHANGE, 'topic', {durable: false})
    await this.channel.assertQueue(this.myQueue, {exclusive: true, durable: false, autoDelete: true})

    try {
      await this.channel.bindQueue(this.myQueue, USER_CENTER_EXCHANGE, this.userNormalTopic(this.userId))
      await this.channel.bindQueue(this.myQueue, USER_CENTER_EXCHANGE, this.userAppTopic(this.userId))
      const {consumerTag} = await this.channel.consume(this.myQueue, async (message: Message) => {
        if (!message) return

        try {
          const messageObj = JSON.parse(message.content.toString())
          this.emit('message', messageObj)
        } catch (e) {
          logger.error('debug message error ' + message.content.toString())
        }
      })

      this.consumerTag = consumerTag
    } catch (e) {

    }
  }

  async disconnect() {

    await this.channel.unbindExchange(USER_CENTER_EXCHANGE, this.myQueue, this.userNormalTopic(this.userId))
    await this.channel.unbindExchange(USER_CENTER_EXCHANGE, this.myQueue, this.userAppTopic(this.userId))
    this.consumerTag && await this.channel.cancel(this.consumerTag)
    await this.channel.deleteQueue(this.myQueue)
  }

  get myQueue(): string {
    return `${this.appId}.${this.id}`
  }


  private userNormalTopic(userId: string) {
    return `user.${userId}`
  }

  private userAppTopic(userId: string) {
    return `user.${userId}.${this.appId}`
  }

  sendTo(userId: string, message: any) {
    this.channel.publish(USER_CENTER_EXCHANGE, this.userNormalTopic(userId), new Buffer(JSON.stringify(message)))
  }

  createRoomRequest(roomConfig) {

  }

  joinRoomRequest(roomId) {

  }

  joinRandomRoomRequest() {

  }
}


